package com.yuyou.fn.report.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.wens.framework.service.impl.SuperServiceImpl;
import com.github.wens.mybatisplus.examples.Example;
import com.github.wens.mybatisplus.plugins.Page;
import com.yuyou.fn.common.constant.ReportResourceEnum;
import com.yuyou.fn.common.util.*;
import com.yuyou.fn.educational.entity.Period;
import com.yuyou.fn.educational.entity.PeriodSegment;
import com.yuyou.fn.educational.entity.ReportConfig;
import com.yuyou.fn.educational.entity.Teacher;
import com.yuyou.fn.educational.service.*;
import com.yuyou.fn.educational.vo.*;
import com.yuyou.fn.platform.permission.DataPermission;
import com.yuyou.fn.report.entity.MergeStudentRegDetail;
import com.yuyou.fn.report.entity.StudentRegDetail;
import com.yuyou.fn.report.mapper.MergeStudentRegDetailMapper;
import com.yuyou.fn.report.service.IMergeStudentRegDetailService;
import com.yuyou.fn.report.vo.*;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * StudentRegDetail 表数据服务层接口实现类
 */
@Service
public class MergeStudentRegDetailServiceImpl extends SuperServiceImpl<MergeStudentRegDetailMapper, MergeStudentRegDetail, Long> implements IMergeStudentRegDetailService {


    @Resource
    private ITeacherRemunerationService teacherRemunerationService;

    @Resource
    private IPeriodService periodService;

    @Resource
    private IPeriodSegmentService periodSegmentService;


    @Resource
    private IReportConfigService reportConfigService;


    @Override
    public Page<MergeStudentRegDetail> findStudentRegByQuery(StudentRegDetailQueryVo studentRegDetailQueryVo, int pageNo, int pageSize) {
        Example<MergeStudentRegDetail> example = MergeStudentRegDetail.createExample();
        example.orderBy("createTime").desc();
        Example.Criteria criteria = example.createCriteria();
        CriteriaUtils.fillCondition(criteria, studentRegDetailQueryVo);
        return findPageByExample(example, pageNo, pageSize);
    }


    @Override
    public List<MergeStudentRegDetail> findListStudentRegByQuery(List<Integer> regStatusList, PeriodQueryRegVo periodQueryRegVo, List<Long> gradeIds, List<Long> periodIds, List<Long> busTeamIds, String... columns) {
        if (busTeamIds == null || busTeamIds.size() <= 0 || regStatusList == null || regStatusList.size() <= 0) {
            return Collections.EMPTY_LIST;
        }
        Example<MergeStudentRegDetail> example = MergeStudentRegDetail.createExample();
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("busTeamId", busTeamIds);
        criteria.andIn("regStatus", regStatusList);

        if (gradeIds != null && gradeIds.size() > 0) {
            criteria.andIn("gradeId", gradeIds);
        }
        if (periodIds != null && periodIds.size() > 0) {
            criteria.andIn("periodId", periodIds);
        }
        CriteriaUtils.fillCondition(criteria, periodQueryRegVo);
        example.orderBy("createTime");
        if (columns != null) {
            example.selectProperties(columns);
        }
        return this.findListByExample(example);
    }

    @Override
    public List<MergeStudentRegDetail> findListByBusTeamIdsPeriodsGradeIds(List<Long> busTeamIds, List<Long> periodIds, List<Long> gradeIds, PeriodQueryRegVo periodQueryRegVo, String... columns) {
        if (busTeamIds == null || busTeamIds.size() <= 0) {
            return Collections.EMPTY_LIST;
        }
        Example<MergeStudentRegDetail> example = MergeStudentRegDetail.createExample();
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("busTeamId", busTeamIds);
        if (periodIds != null && periodIds.size() > 0) {
            criteria.andIn("periodId", periodIds);
        }
        if (gradeIds != null && gradeIds.size() > 0) {
            criteria.andIn("gradeId", gradeIds);
        }
        CriteriaUtils.fillCondition(criteria, periodQueryRegVo);
        if (columns != null) {
            example.selectProperties(columns);
        }
        return this.findListByExample(example);
    }

    @Override
    public List<MergeStudentRegDetail> findBySeniorIdsPeriodIds(List<Long> seniorIds, List<Long> periodIds, PeriodQueryRegVo periodQueryRegVo, String... columns) {
        if (seniorIds == null || seniorIds.size() <= 0) {
            return Collections.EMPTY_LIST;
        }
        Example<MergeStudentRegDetail> example = MergeStudentRegDetail.createExample();
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("seniorId", seniorIds);
        if (periodIds != null && periodIds.size() > 0) {
            criteria.andIn("periodId", periodIds);
        }
        CriteriaUtils.fillCondition(criteria, periodQueryRegVo);
        if (columns != null) {
            example.selectProperties(columns);
        }
        return this.findListByExample(example);
    }

    @Override
    public List<MergeStudentRegDetail> findByCounselorIdsPeriodIdsStates(List<Long> counselorIds, List<Long> periodIds, List<Integer> studentStates, PeriodQueryRegVo periodQueryRegVo, String... columns) {
        if (counselorIds == null || counselorIds.size() <= 0) {
            return Collections.EMPTY_LIST;
        }
        Example<MergeStudentRegDetail> example = MergeStudentRegDetail.createExample();
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("counselorId", counselorIds);
        if (periodIds != null && periodIds.size() > 0) {
            criteria.andIn("periodId", periodIds);
        }
        if (studentStates != null && studentStates.size() > 0) {
            criteria.andIn("studentState", studentStates);
        }
        CriteriaUtils.fillCondition(criteria, periodQueryRegVo);
        if (columns != null) {
            example.selectProperties(columns);
        }
        return this.findListByExample(example);
    }

    @Override
    public List<MergeStudentRegDetail> findByAreaTeamIdPeriodIds(Long areaTeamId, List<Long> periodIds, PeriodQueryRegVo periodQueryRegVo, String... columns) {
        if (areaTeamId == null || Utils.checkListEmpty(periodIds)) {
            return Collections.EMPTY_LIST;
        }
        Example<MergeStudentRegDetail> example = MergeStudentRegDetail.createExample();
        Example.Criteria criteria = example.createCriteria();
        if (periodIds != null && periodIds.size() > 0) {
            criteria.andIn("periodId", periodIds);
        }
        criteria.andEqualTo("areaTeamId", areaTeamId);
        CriteriaUtils.fillCondition(criteria, periodQueryRegVo);
        if (columns != null) {
            example.selectProperties(columns);
        }
        return this.findListByExample(example);
    }

    @Override
    public List<MergeStudentRegDetail> findByTeacherIdsPeriodIds(List<Long> teacherIds, List<Long> periodIds, PeriodQueryRegVo periodQueryRegVo, String... columns) {
        if (teacherIds == null || teacherIds.size() <= 0) {
            return Collections.EMPTY_LIST;
        }
        Example<MergeStudentRegDetail> example = MergeStudentRegDetail.createExample();
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("teacherId", teacherIds);
        if (periodIds != null && periodIds.size() > 0) {
            criteria.andIn("periodId", periodIds);
        }
        CriteriaUtils.fillCondition(criteria, periodQueryRegVo);
        if (columns != null) {
            example.selectProperties(columns);
        }
        return this.findListByExample(example);
    }

    @Override
    public List<MergeStudentRegDetail> findByClassId(PeriodQueryRegVo periodQueryRegVo, List<Long> classIds, String... columns) {

        if (classIds == null || classIds.size() <= 0) {
            return Collections.EMPTY_LIST;
        }
        Example<MergeStudentRegDetail> example = MergeStudentRegDetail.createExample();
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("classId", classIds);
        CriteriaUtils.fillCondition(criteria, periodQueryRegVo);
        if (columns != null) {
            example.selectProperties(columns);
        }
        return this.findListByExample(example);
    }


    @Override
    public List<RankByContinueClassVo> buildTeacherContinueRate(String key, List<RegRelativeVo> regRelativeVoList, List<Long> seqIdList, List<Long> stepIdList, Map<Long, Map<Integer, PeriodSegment>> periodSegmentMap) {
        List<RankByContinueClassVo> rankByContinueClassVoList = new ArrayList<>();
        List<TeacherContinueRateVo> teacherContinueRateVoList = this.findTeacherContinueRate(key, regRelativeVoList, seqIdList, stepIdList);
        Collections.sort(teacherContinueRateVoList, new Comparator<TeacherContinueRateVo>() {
            @Override
            public int compare(TeacherContinueRateVo o1, TeacherContinueRateVo o2) {
                return o1.getRate() >= o2.getRate() ? -1 : 1;
            }
        });
        Integer rankNo = 1;
        for (TeacherContinueRateVo teacherContinueRateVo : teacherContinueRateVoList) {
            RankByContinueClassVo rankByContinueClassVo = new RankByContinueClassVo();
            rankByContinueClassVo.setRate(teacherContinueRateVo.getRate());
            rankByContinueClassVo.setTeacherId(teacherContinueRateVo.getTeacherId());
            rankByContinueClassVo.setRankNo(rankNo++);
            rankByContinueClassVoList.add(rankByContinueClassVo);
        }
        return rankByContinueClassVoList;
    }

    @Override
    public List<RankByContinueClassVo> findTeacherContinueRankRate(Teacher teacher, Long periodId) {
        Period period = periodService.findById(periodId);
        List<Period> seqList = periodService.findBySequentialId(period.getAreaTeamId(), periodId);
        List<Period> stepList = periodService.findByStepId(period.getAreaTeamId(), periodId);
        List<Long> seqIdList = BeanUtils.toList(seqList, "periodId");
        List<Long> stepIdList = BeanUtils.toList(stepList, "periodId");
        List<Long> seqStepList = new ArrayList<>();
        seqStepList.addAll(seqIdList);
        seqStepList.addAll(stepIdList);

        List<RegRelativeVo> regRelativeVoList = null;
        String key = "teacherId";
        PeriodQueryRegVo periodQueryRegVo = new PeriodQueryRegVo();
        periodQueryRegVo.setPeriodIds(Arrays.asList(periodId));
        periodQueryRegVo.setAreaTeamId(teacher.getAreaTeamId());
        periodQueryRegVo.setChargingStatus(2);
        periodQueryRegVo.setRegStatus(0);
        RegRelativceQueryVo regRelativceQueryVo = new RegRelativceQueryVo();
        //regRelativceQueryVo.setBigRecordLectureNum(5);
        if (teacher.getAccessType() == 1) {
            regRelativceQueryVo.setPeriodIds(seqStepList);
            regRelativceQueryVo.setNeedSameSubject(1);
            //periodQueryRegVo.setLectureNum(5);

            key = "seniorId";
        }
        List<Long> allPeriodIds = new ArrayList<>();
        allPeriodIds.add(periodId);
        allPeriodIds.addAll(seqStepList);
        List<PeriodSegment> periodSegmentList = periodSegmentService.findByPeriodSegmentListByPeriodIds(allPeriodIds);
        Map<Long, Map<Integer, PeriodSegment>> periodSegmentMap = periodSegmentService.periodSegmentToMapGroup(periodSegmentList);


        regRelativeVoList = this.queryRegRelative(periodQueryRegVo, regRelativceQueryVo);
        regRelativeVoList=this.filterListByEffectiveLectureNum(regRelativeVoList,periodSegmentMap);
        regRelativeVoList=this.filterListByReportConfig(allPeriodIds,regRelativeVoList, ReportResourceEnum.薪酬教师续读.id);

        List<RankByContinueClassVo> rankByContinueClassVos = this.buildTeacherContinueRate(key, regRelativeVoList, seqIdList, stepIdList, periodSegmentMap);

        return rankByContinueClassVos;
    }


    @Override
    public List<ClassRemunerationRankVo> findRegNumOrRemuneration(Teacher teacher, Long periodId) {
        Period period = periodService.findById(periodId);
        List<Period> seqList = periodService.findBySequentialId(period.getAreaTeamId(), periodId);
        List<Period> stepList = periodService.findByStepId(period.getAreaTeamId(), periodId);
        List<Long> seqIdList = BeanUtils.toList(seqList, "periodId");
        List<Long> stepIdList = BeanUtils.toList(stepList, "periodId");
        List<Long> seqStepList = new ArrayList<>();
        seqStepList.addAll(seqIdList);
        seqStepList.addAll(stepIdList);

        List<ClassRemunerationRankVo> classRemunerationRankVoList = null;
        PeriodQueryRegVo periodQueryRegVo = new PeriodQueryRegVo();
        periodQueryRegVo.setRegStatus(0);
        // periodQueryRegVo.setChargingStatus(2);
        periodQueryRegVo.setAreaTeamId(teacher.getAreaTeamId());
        periodQueryRegVo.setPeriodIds(Arrays.asList(periodId));
        periodQueryRegVo.setChargingStatus(2);
        RegRelativceQueryVo regRelativceQueryVo = new RegRelativceQueryVo();
        //regRelativceQueryVo.setBigRecordLectureNum(5);
        regRelativceQueryVo.setRecordChargingStatus(2);
        regRelativceQueryVo.setPeriodIds(seqStepList);
        regRelativceQueryVo.setNeedSameSubject(1);

        List<Long> allPeriodIds = new ArrayList<>();
        allPeriodIds.add(periodId);
        allPeriodIds.addAll(seqStepList);
        List<PeriodSegment> periodSegmentList = periodSegmentService.findByPeriodSegmentListByPeriodIds(allPeriodIds);
        Map<Long, Map<Integer, PeriodSegment>> periodSegmentMap = periodSegmentService.periodSegmentToMapGroup(periodSegmentList);


        if (teacher.getAccessType() == 1) {
            List<RegRelativeVo> regRelativeVoList = this.queryRegRelative(periodQueryRegVo, regRelativceQueryVo);
            regRelativeVoList=this.filterListByEffectiveLectureNum(regRelativeVoList,periodSegmentMap);
            regRelativeVoList=this.filterListByReportConfig(allPeriodIds,regRelativeVoList,ReportResourceEnum.薪酬教师续读.id);

            List<TeacherContinueRateVo> teacherContinueRateVoList = this.findTeacherContinueRate("seniorId", regRelativeVoList, seqIdList, stepIdList);//this.findTeacherContinueRate(regRelativceList,studentRegDetailList,"seniorId");
            Collections.sort(teacherContinueRateVoList, new Comparator<TeacherContinueRateVo>() {
                @Override
                public int compare(TeacherContinueRateVo o1, TeacherContinueRateVo o2) {
                    return o1.getTotal() >= o2.getTotal() ? -1 : 1;
                }
            });
            classRemunerationRankVoList = new ArrayList<>(teacherContinueRateVoList.size());
            Integer rank = 1;
            for (TeacherContinueRateVo teacherContinueRateVo : teacherContinueRateVoList) {
                ClassRemunerationRankVo classRemunerationRankVo = new ClassRemunerationRankVo();
                classRemunerationRankVo.setTeacherId(teacherContinueRateVo.getTeacherId());
                classRemunerationRankVo.setAmount(new BigDecimal(teacherContinueRateVo.getTotal()));
                classRemunerationRankVo.setRankNo(rank++);
                classRemunerationRankVoList.add(classRemunerationRankVo);
            }

        } else {
            classRemunerationRankVoList = teacherRemunerationService.classRemunerationRank(teacher.getAreaTeamId(), periodId);
        }
        return classRemunerationRankVoList;
    }


    @Override
    public List<StudentAmountRankVo> buildStudentAmountRank(String key, List<RegRelativeVo> regRelativeVoList, List<Long> seqIdList, List<Long> stepIdList) {
        List<StudentAmountRankVo> studentAmountRankVoList = new ArrayList<>();
        List<TeacherContinueRateVo> teacherContinueRateVoList = this.findTeacherContinueRate(key, regRelativeVoList, seqIdList, stepIdList);
        Collections.sort(teacherContinueRateVoList, new Comparator<TeacherContinueRateVo>() {
            @Override
            public int compare(TeacherContinueRateVo o1, TeacherContinueRateVo o2) {
                return o1.getTotal() >= o2.getTotal() ? -1 : 1;
            }
        });
        Integer rankNo = 1;
        for (TeacherContinueRateVo teacherContinueRateVo : teacherContinueRateVoList) {
            StudentAmountRankVo studentAmountRankVo = new StudentAmountRankVo();
            studentAmountRankVo.setTeacherId(teacherContinueRateVo.getTeacherId());
            studentAmountRankVo.setRankNo(rankNo++);
            studentAmountRankVo.setStudentAmount(teacherContinueRateVo.getTotal());
            studentAmountRankVoList.add(studentAmountRankVo);
        }
        return studentAmountRankVoList;
    }

    @Override
    public List<StudentAmountRankVo> findStudentAmountRank(Teacher teacher, Long periodId) {
        Period period = periodService.findById(periodId);
        List<Period> seqList = periodService.findBySequentialId(period.getAreaTeamId(), periodId);
        List<Period> stepList = periodService.findByStepId(period.getAreaTeamId(), periodId);
        List<Long> seqIdList = BeanUtils.toList(seqList, "periodId");
        List<Long> stepIdList = BeanUtils.toList(stepList, "periodId");
        List<Long> seqStepList = new ArrayList<>();
        seqStepList.addAll(seqIdList);
        seqStepList.addAll(stepIdList);
        List<RegRelativeVo> regRelativeVoList = null;
        String key = "teacherId";
        PeriodQueryRegVo periodQueryRegVo = new PeriodQueryRegVo();
        periodQueryRegVo.setRegStatus(0);
        periodQueryRegVo.setAreaTeamId(teacher.getAreaTeamId());
        periodQueryRegVo.setPeriodIds(Arrays.asList(periodId));
        periodQueryRegVo.setChargingStatus(2);
        RegRelativceQueryVo regRelativceQueryVo = new RegRelativceQueryVo();
        //regRelativceQueryVo.setBigRecordLectureNum(5);
        regRelativceQueryVo.setRecordChargingStatus(2);
        regRelativceQueryVo.setPeriodIds(seqStepList);
        regRelativceQueryVo.setNeedSameSubject(1);
        if (teacher.getAccessType() == 1) {
            key = "seniorId";
        }
        List<Long> allPeriodIds = new ArrayList<>();
        allPeriodIds.add(periodId);
        allPeriodIds.addAll(seqStepList);
        List<PeriodSegment> periodSegmentList = periodSegmentService.findByPeriodSegmentListByPeriodIds(allPeriodIds);
        Map<Long, Map<Integer, PeriodSegment>> periodSegmentMap = periodSegmentService.periodSegmentToMapGroup(periodSegmentList);


        regRelativeVoList = this.queryRegRelative(periodQueryRegVo, regRelativceQueryVo);
        regRelativeVoList =this.filterListByEffectiveLectureNum(regRelativeVoList,periodSegmentMap);
        regRelativeVoList=this.filterListByReportConfig(allPeriodIds,regRelativeVoList,ReportResourceEnum.薪酬教师续读.id);

        List<StudentAmountRankVo> studentAmountRankVoList = this.buildStudentAmountRank(key, regRelativeVoList, seqIdList, stepIdList);
        return studentAmountRankVoList;
    }


    @Override
    public List<TeacherContinueRateVo> findTeacherContinueRate(String key, List<RegRelativeVo> regRelativeVoList, List<Long> seqIdList, List<Long> stepIdList) {
        Map<Long, List<RegRelativeVo>> relativeMap = BeanUtils.toGroup(regRelativeVoList, key);
        List<TeacherContinueRateVo> teacherContinueRateVoList = new ArrayList<>(relativeMap.size());
        for (Map.Entry<Long, List<RegRelativeVo>> entry : relativeMap.entrySet()) {
            Map<String, Integer> recordMap = new HashMap<>();
            Long teacherId = entry.getKey();
            TeacherContinueRateVo teacherContinueRateVo = new TeacherContinueRateVo();
            teacherContinueRateVo.setTeacherId(teacherId);
            List<RegRelativeVo> oneTeacherStudentRegDetail = entry.getValue();
            Integer total = 0;
            Integer continueNum = 0;
            for (RegRelativeVo regRelativeVo : oneTeacherStudentRegDetail) {

                Long regId = regRelativeVo.getRegId();
                Long relativePeriodId = regRelativeVo.getRelativePeriodId();
                Long studentId = regRelativeVo.getStudentId();
                Integer chargingStatus = regRelativeVo.getChargingStatus();

                if (!recordMap.containsKey(regId.toString()) && chargingStatus == 2) {
                    total = total + 1;
                    recordMap.put(regId.toString(), 1);
                }

                if (regRelativeVo.getRelativeRegId()==null) {
                    continue;
                }
                if ("seniorId".equals(key)) {
                    if ((seqIdList != null && seqIdList.contains(relativePeriodId)) || (stepIdList != null && stepIdList.contains(relativePeriodId))) {
                        continueNum++;
                    }
                } else if ("teacherId".equals(key)) {
                    if (!recordMap.containsKey(studentId + "_" + 4) && seqIdList != null && seqIdList.contains(relativePeriodId)) {
                        continueNum++;
                        recordMap.put(studentId + "_" + 4, 1);
                    }
                    if (!recordMap.containsKey(studentId + "_" + 5) && stepIdList != null && stepIdList.contains(relativePeriodId)) {
                        continueNum++;
                        recordMap.put(studentId + "_" + 5, 1);
                    }
                }
            }
            teacherContinueRateVo.setTotal(total);
            teacherContinueRateVo.setContinueNum(continueNum);
            if (total == 0 || continueNum == 0) {
                teacherContinueRateVo.setRate(0.0);
            } else {
                double f1 = new BigDecimal((float) continueNum / total).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                teacherContinueRateVo.setRate(f1);
            }
            teacherContinueRateVoList.add(teacherContinueRateVo);
        }
        return teacherContinueRateVoList;
    }

    @Override
    public List<ClassBigRegNum> countBigRegNumByClassId(List<Long> busTeamIds, List<Long> periodIds, List<Long> gradeIds, List<Long> subjectIds, Integer lectureNum) {
        return autoMapper.countBigRegNumByClassId(busTeamIds, periodIds, gradeIds, subjectIds, lectureNum);
    }

    @Override
    public List<AreaTeamRegDetailVo> countAreaTeamRegDetail(StudentRegDetailQueryVo studentRegDetailQueryVo) {
        return autoMapper.countAreaTeamRegDetail(studentRegDetailQueryVo);
    }

    @Override
    public List<MergeStudentRegDetail> findListByAreaTeamIdPeriodIdsGradeId(Long areaTeamId, List<Long> periodIds, Long gradeId, String... columns) {
        if (areaTeamId == null || Utils.checkListEmpty(periodIds) || gradeId == null) {
            return Collections.EMPTY_LIST;
        }
        Example<MergeStudentRegDetail> example = MergeStudentRegDetail.createExample();
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("areaTeamId", areaTeamId);
        criteria.andIn("periodId", periodIds);
        criteria.andEqualTo("regStatus", 0);
        criteria.andEqualTo("chargingStatus", 2);
        //criteria.andGreaterThan("lectureNum", bigLectureNum);
        criteria.andEqualTo("gradeId", gradeId);

        if (columns != null) {
            example.selectProperties(columns);
        }
        return findListByExample(example);
    }


    @Override
    public List<RegDetailByClass> findClassRegDetail(List<Long> classIds) {
        return autoMapper.findClassRegDetail(classIds);
    }

    @Override
    public List<MergeStudentRegDetail> findByStudentIdsPeriodIds(List<Long> studentIds, List<Long> periodIds, PeriodQueryRegVo periodQueryRegVo, String... columns) {
        if (Utils.checkListEmpty(studentIds) || Utils.checkListEmpty(periodIds)) {
            return Collections.EMPTY_LIST;
        }
        Example<MergeStudentRegDetail> example = MergeStudentRegDetail.createExample();
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("studentId", studentIds);
        criteria.andIn("periodId", periodIds);
        CriteriaUtils.fillCondition(criteria, periodQueryRegVo);
        if (columns != null) {
            example.selectProperties(columns);
        }
        return findListByExample(example);
    }

    @Override
    public List<MergeStudentRegDetail> findByAreaTeamPeriodIds(Long areaTeamId, List<Long> periodIds, PeriodQueryRegVo periodQueryRegVo, String... columns) {
        if (areaTeamId == null || Utils.checkListEmpty(periodIds)) {
            return Collections.EMPTY_LIST;
        }
        Example<MergeStudentRegDetail> example = MergeStudentRegDetail.createExample();
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("areaTeamId", areaTeamId);
        criteria.andIn("periodId", periodIds);
        CriteriaUtils.fillCondition(criteria, periodQueryRegVo);
        if (columns != null) {
            example.selectProperties(columns);
        }
        return findListByExample(example);
    }

    @Override
    public List<RegRelativeVo> queryRegRelative(PeriodQueryRegVo periodQueryRegVo, RegRelativceQueryVo regRelativceQueryVo) {
        List<RegRelativeVo> regRelativeVoList = autoMapper.queryRegRelative(periodQueryRegVo, regRelativceQueryVo);
        return regRelativeVoList;
    }

    @Override
    public List<RegRelativeVo> filterListByEffectiveLectureNum(List<RegRelativeVo> regRelativeVos, Map<Long, Map<Integer, PeriodSegment>> periodSegmentMap) {
        if (periodSegmentMap!=null){
            Iterator<RegRelativeVo> iterator=regRelativeVos.iterator();
            while (iterator.hasNext()){
                RegRelativeVo regRelativeVo=iterator.next();
                if (!this.checkClassBigEffectiveLectureNum(regRelativeVo.getLectureNum(), regRelativeVo.getSegmentNo(), regRelativeVo.getPeriodId(), periodSegmentMap)) {
                    iterator.remove();
                    continue;
                }
                if (!this.checkClassBigEffectiveLectureNum(regRelativeVo.getRelativeLectureNum(), regRelativeVo.getRelativeSegmentNo(), regRelativeVo.getRelativePeriodId(), periodSegmentMap)){
                    regRelativeVo.setRelativeRegId(null);
                }
            }
        }
        return regRelativeVos;
    }

    @Override
    public List<RegRelativeVo> filterListByReportConfig(List<Long> periodIds,List<RegRelativeVo> regRelativeVos, Long resourceId) {
        List<ReportConfig> reportConfigList=reportConfigService.findByPeriodIdsResourceId(periodIds,resourceId);
        if (reportConfigList.isEmpty()){
            return  regRelativeVos;
        }
        Map<Long,Integer> twoWayRecordClassMap=new HashMap<>();// 记录双向剔除的数据
        Map<Long,Integer> oneWayRecordClassMap=new HashMap<>();// 记录单向剔除的数据
        for (ReportConfig reportConfig:reportConfigList){
            ReportConfigDetailVo reportConfigDetailVo=JSONObject.parseObject(reportConfig.getConfig(),ReportConfigDetailVo.class);

            List<Long> classIds=reportConfigDetailVo.getExcludeClassIds();
            if (reportConfig.getType()==1){
                for (Long classId:classIds){
                    twoWayRecordClassMap.put(classId,1);
                }
            }
            if (reportConfig.getType()==2){
                for (Long classId:classIds){
                    oneWayRecordClassMap.put(classId,1);
                }
            }
        }
        Iterator<RegRelativeVo> iterator=regRelativeVos.iterator();
        while (iterator.hasNext()){
            RegRelativeVo regRelativeVo=iterator.next();
            if (twoWayRecordClassMap.containsKey(regRelativeVo.getClassId()) || oneWayRecordClassMap.containsKey(regRelativeVo.getClassId())){
                iterator.remove();
                continue;
            }
            if (twoWayRecordClassMap.containsKey(regRelativeVo.getRelativeClassId())){
                regRelativeVo.setRelativeRegId(null);
            }
        }
        return regRelativeVos;
    }

    @Override
    public List<MergeStudentRegDetail> filterRegByEffectiveLectureNum(List<MergeStudentRegDetail> mergeStudentRegDetails, Map<Long, Map<Integer, PeriodSegment>> periodSegmentMap) {
        if (periodSegmentMap!=null){
            Iterator<MergeStudentRegDetail> iterator=mergeStudentRegDetails.iterator();
            while (iterator.hasNext()){
                MergeStudentRegDetail mergeStudentRegDetail=iterator.next();
                if (!this.checkClassBigEffectiveLectureNum(mergeStudentRegDetail.getLectureNum(), mergeStudentRegDetail.getSegmentNo(), mergeStudentRegDetail.getPeriodId(), periodSegmentMap)) {
                    iterator.remove();
                }
            }
        }
        return mergeStudentRegDetails;
    }

    @Override
    public List<MergeStudentRegDetail> filteRegByReportConfig(List<Long> periodIds, List<MergeStudentRegDetail> mergeStudentRegDetails, Long resourceId) {

        List<ReportConfig> reportConfigList=reportConfigService.findByPeriodIdsResourceId(periodIds,resourceId);
        if (reportConfigList.isEmpty()){
            return  mergeStudentRegDetails;
        }
        Map<Long,Integer> recordClassMap=new HashMap<>();
        for (ReportConfig reportConfig:reportConfigList){
            ReportConfigDetailVo reportConfigDetailVo=JSONObject.parseObject(reportConfig.getConfig(),ReportConfigDetailVo.class);

            List<Long> classIds=reportConfigDetailVo.getExcludeClassIds();
            for (Long classId:classIds){
                recordClassMap.put(classId,1);
            }
        }
        Iterator<MergeStudentRegDetail> iterator=mergeStudentRegDetails.iterator();
        while (iterator.hasNext()){
            MergeStudentRegDetail mergeStudentRegDetail=iterator.next();
            if (recordClassMap.containsKey(mergeStudentRegDetail.getClassId())){
                iterator.remove();
                continue;
            }

        }
        return mergeStudentRegDetails;
    }

    @Override
    public List<MergeStudentRegDetail> findByStudentIdsQueryVo(List<Long> studentIds, StudentRegDetailQueryVo studentRegDetailQueryVo, String... columns) {
        if (Utils.checkListEmpty(studentIds)) {
            return Collections.EMPTY_LIST;
        }
        Example<MergeStudentRegDetail> example = MergeStudentRegDetail.createExample();
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("studentId", studentIds);
        CriteriaUtils.fillCondition(criteria, studentRegDetailQueryVo);
        if (columns != null) {
            example.selectProperties(columns);
        }
        return findListByExample(example);
    }

    @Override
    public List<SeniorStudentDetailVo> findSeniorStudentDetail() {
        return autoMapper.findSeniorStudentDetail();
    }


    @Override
    public List<MergeStudentRegDetail> findByStudentPhoneNosQueryVo(List<String> studentPhoneNos, StudentRegDetailQueryVo studentRegDetailQueryVo, String... columns) {
        if (Utils.checkListEmpty(studentPhoneNos)) {
            return Collections.EMPTY_LIST;
        }
        Example<MergeStudentRegDetail> example = MergeStudentRegDetail.createExample();
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("studentPhoneNo", studentPhoneNos);
        CriteriaUtils.fillCondition(criteria, studentRegDetailQueryVo);
        if (columns != null) {
            example.selectProperties(columns);
        }
        return findListByExample(example);
    }

    @Override
    public Page<MergeStudentRegDetail> findRefundStudentRegPage(DataPermission dataPermission, StudentRegDetailQueryVo studentRegDetailQueryVo, int pageNo, int pageSize) {
        if (Utils.checkListEmpty(dataPermission.getBusTeamIds())) {
            return new Page<>(0, 0);
        }
        Example<MergeStudentRegDetail> example = MergeStudentRegDetail.createExample();
        Example.Criteria criteria = example.createCriteria();
        CriteriaUtils.fillCondition(criteria, studentRegDetailQueryVo);
        criteria.andGreaterThan("refundAmount", 0);
        return this.findPageByExample(example, pageNo, pageSize);
    }

    @Override
    public Page<PeriodBusTeamGradeRegVo> findRegSituationPage(DataPermission dataPermission, StudentRegDetailQueryVo studentRegDetailQueryVo, int pageNo, int pageSize) {
        if (Utils.checkListEmpty(dataPermission.getBusTeamIds())) {
            return new Page<>(0, 0);
        }
        studentRegDetailQueryVo.setBusTeamIds(dataPermission.getBusTeamIds());
        List<PeriodBusTeamGradeRegVo> regSituationList = this.autoMapper.findRegSituation(studentRegDetailQueryVo, (pageNo - 1) * pageSize, pageSize);
        Integer total = this.autoMapper.countRegSituation(studentRegDetailQueryVo);
        Page<PeriodBusTeamGradeRegVo> regSituationVoPage = new Page<>(pageNo, pageSize);
        regSituationVoPage.setRecords(regSituationList);
        regSituationVoPage.setTotal(total);
        return regSituationVoPage;
    }

    @Override
    public SumRegVo findSumReg(DataPermission dataPermission, StudentRegDetailQueryVo studentRegDetailQueryVo) {
        if (Utils.checkListEmpty(dataPermission.getBusTeamIds())) {
            return null;
        }
        studentRegDetailQueryVo.setBusTeamIds(dataPermission.getBusTeamIds());

        return this.autoMapper.findSumReg(studentRegDetailQueryVo);
    }

    @Override
    public List<TeacherPeriodRefundDetailVo> findTeacherPeriodRefundDetail(long teacherId, long periodId) {
        return this.autoMapper.findTeacherPeriodRefundDetail(teacherId, periodId);
    }

    @Override
    public List<BusTeamPeriodGradeRegNumVo> findBusTeamPeriodGradeRegNum(SimpleQueryVo simpleQueryVo, int begin, int pageSize) {
        return this.autoMapper.findBusTeamPeriodGradeRegNum(simpleQueryVo, begin, pageSize);
    }

    @Override
    public Integer countBusTeamPeriodGradeRegNum(SimpleQueryVo simpleQueryVo) {
        return this.autoMapper.countBusTeamPeriodGradeRegNum(simpleQueryVo);
    }

    @Override
    public void deleteByStudentIdClassId(long studentId, long classId) {
        Example<MergeStudentRegDetail> example = MergeStudentRegDetail.createExample();
        example.createCriteria().andEqualTo("studentId", studentId).andEqualTo("classId", classId);
        this.deleteByExample(example);
    }

    @Override
    public MergeStudentRegDetail findByStudentIdClassId(long studentId, long classId) {
        Example<MergeStudentRegDetail> example = MergeStudentRegDetail.createExample();
        example.createCriteria().andEqualTo("studentId", studentId).andEqualTo("classId", classId);
        return this.findOneByExample(example);
    }

    @Override
    public void deleteByStudentId(long studentId) {
        Example<MergeStudentRegDetail> example = MergeStudentRegDetail.createExample();
        example.createCriteria().andEqualTo("studentId", studentId);
        this.deleteByExample(example);
    }

    @Override
    public List<MergeStudentRegDetail> findByStudentIdsClassIds(List<Long> studentIds, List<Long> classIds, String... columns) {
        if (Utils.checkListEmpty(studentIds) || Utils.checkListEmpty(classIds)) {
            return Collections.EMPTY_LIST;
        }
        Example<MergeStudentRegDetail> example = MergeStudentRegDetail.createExample();
        example.createCriteria().andIn("studentId", studentIds).andIn("classId", classIds);
        if (columns != null) {
            example.selectProperties(columns);
        }
        return this.findListByExample(example);
    }

    @Override
    public Boolean checkClassBigEffectiveLectureNum(Integer lectureNum, Integer segmentNo, Long periodId, Map<Long, Map<Integer, PeriodSegment>> periodSegmentMap) {
        if (lectureNum == null || segmentNo == null || periodId == null) {
            return false;
        }
        Map<Integer, PeriodSegment> segmentMap = periodSegmentMap.get(periodId);
        if (segmentMap == null) {
            return false;
        }
        PeriodSegment periodSegment = segmentMap.get(segmentNo);
        if (periodSegment == null) {
            return false;
        }
        Integer checkNum = periodSegment.getEffectiveLectureNum() == null ? 6 : periodSegment.getEffectiveLectureNum();
        if (lectureNum >= checkNum) {
            return true;
        }

        return false;
    }


    @Override
    public List<NewOldStudentBranchAdvanceVo> findNewOldStudentBranchAmount(StudentRegDetailQueryVo studentRegDetailQueryVo) {


        List<NewOldStudentBranchAdvanceVo> newOldStudentBranchAdvanceVoList = this.autoMapper.findNewOldStudentBranchAmount(studentRegDetailQueryVo);
        return newOldStudentBranchAdvanceVoList;
    }

    @Override
    public List<SeqStepStudentBranchAdvanceVo> findSeqStepStudentBranchAmount(RegRelativceQueryVo regRelativceQueryVo, PeriodQueryRegVo periodQueryRegVo) {
        List<SeqStepStudentBranchAdvanceVo> seqStepStudentBranchAdvanceVoList = this.autoMapper.findSeqStepStudentBranchAmount(regRelativceQueryVo, periodQueryRegVo);

        return seqStepStudentBranchAdvanceVoList;
    }


    @Override
    public List<NoCounselorBranchVo> countBusTeamOlineNoCounselorBranch(StudentRegDetailQueryVo studentRegDetailQueryVo) {
        return this.autoMapper.countBusTeamOlineNoCounselorBranch(studentRegDetailQueryVo);
    }

    @Override
    public List<CounselorBranchAdvanceVo> findCounselorBranchAdvanceByStudentState(StudentRegDetailQueryVo studentRegDetailQueryVo) {
        return this.autoMapper.findCounselorBranchAdvanceByStudentState(studentRegDetailQueryVo);
    }


    @Override
    public List<ClassPreIncomeDetailVo> findClassPreIncomeDetailVo(ClassPreIncomeDetailQueryVo classPreIncomeDetailQueryVo) {
        Date startTime = classPreIncomeDetailQueryVo.getCountStartTime();
        Date endTime = classPreIncomeDetailQueryVo.getCountEndTime();
        List<ClassPreIncomeDetailVo> classPreIncomeDetailVos = autoMapper.findClassPreIncomeDetailVo(classPreIncomeDetailQueryVo);

        List<Long> classIds = BeanUtils.toList(classPreIncomeDetailVos, "classId");
        List<ClassRealAmount> countDetails = null;
        if (classIds.size() != 0) {
            countDetails = autoMapper.countRealAmount(classIds);
        }
        Map<Long, ClassRealAmount> realAmountMap = BeanUtils.toMap(countDetails, "classId");
        BigDecimal totalRealAmount = BigDecimal.ZERO;
        int totalLectureAmount = 0;
        int totalAttendlectureAmount = 0;

        for (ClassPreIncomeDetailVo item : classPreIncomeDetailVos) {
            Long classId = item.getClassId();
            BigDecimal realAmount;
            ClassRealAmount classRealAmount = realAmountMap.get(classId);
            if (null == classRealAmount) {
                realAmount = BigDecimal.ZERO;
            } else {
                realAmount = classRealAmount.getRealAmount();
            }
            int lectureAmount = item.getLectureAmount();
            int attendLectureAmount = item.getAttendLectureAmount();
            item.setCountStartTime(TimeUtils.date2String(startTime, "yyyy-MM-dd"));
            item.setCountEndTime(TimeUtils.date2String(endTime, "yyyy-MM-dd"));
            BigDecimal income = BigDecimals.calProportion(new BigDecimal(attendLectureAmount), realAmount, new BigDecimal(lectureAmount));
            item.setRealAmount(BigDecimals.toFixed2(realAmount, 2));
            item.setIncome(BigDecimals.toFixed2(income, 2));
            totalRealAmount = totalRealAmount.add(realAmount);
            totalLectureAmount += lectureAmount;
            totalAttendlectureAmount += attendLectureAmount;
        }
        ClassPreIncomeDetailVo totalItem = getTotalItem(totalRealAmount, totalLectureAmount, totalAttendlectureAmount);
        classPreIncomeDetailVos.add(totalItem);

        return classPreIncomeDetailVos;
    }

    private ClassPreIncomeDetailVo getTotalItem(BigDecimal totalRealAmount, int totalLectureAmount,
                                                int totalAttendlectureAmount) {
        BigDecimal totalIncome = BigDecimals.calProportion(new BigDecimal(totalAttendlectureAmount),
                totalRealAmount, new BigDecimal(totalLectureAmount));
        ClassPreIncomeDetailVo totalItem = new ClassPreIncomeDetailVo();
        totalItem.setCountStartTime("汇总");
        totalItem.setRealAmount(totalRealAmount);
        totalItem.setLectureAmount(totalLectureAmount);
        totalItem.setAttendLectureAmount(totalAttendlectureAmount);
        totalItem.setIncome(BigDecimals.toFixed2(totalIncome, 2));
        return totalItem;
    }

    @Override
    public Long countReadByClassIds(List<Long> classIds) {
        if (Utils.isEmpty(classIds)) return 0l;
        Example<MergeStudentRegDetail> example=MergeStudentRegDetail.createExample();
        Example.Criteria criteria=example.createCriteria();
        criteria.andIn("classId",classIds);
        criteria.andEqualTo("regStatus",0);
        return this.countByExample(example);
    }

    public List<MergeStudentRegDetail> findByStudentIdPeriodIdsChargingStatuses(long studentId, List<Long> periodIds, List<Integer> chargingStatuses) {
        Example<MergeStudentRegDetail> example = MergeStudentRegDetail.createExample();
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("studentId",studentId);
        criteria.andIn("periodId",periodIds);
        criteria.andIn("chargingStatus",chargingStatuses);
        example.orderBy("createTime");
        return this.findListByExample(example);
    }

    @Override
    public List<MergeStudentRegDetail> findByStudentIdsPeriodIdsChargingStatuses(List<Long> studentIds, List<Long> periodIds, List<Integer> chargingStatuses) {
        Example<MergeStudentRegDetail> example = MergeStudentRegDetail.createExample();
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("studentId",studentIds);
        criteria.andIn("periodId",periodIds);
        criteria.andIn("chargingStatus",chargingStatuses);
        return this.findListByExample(example);
    }

    @Override
    public List<CampusPeriodsStudentNumVo> findCampusPeriodsRegNum(List<Long> periodIds) {
        if (Utils.isEmpty(periodIds)){
            return Collections.EMPTY_LIST;
        }
        return this.autoMapper.findCampusPeriodsRegNum(periodIds);
    }

    @Override
    public List<ClassAmountVo> findClassAmountByPeriodId(long periodId) {
        return this.autoMapper.findClassAmountByPeriodId(periodId);
    }
}